/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package technotheist.imgcog.features;

/**
 *
 * @author Mitch
 */
public final class ConvolutionKernel {

    public final int radiusX, radiusY;
    private final float[] convolveKernel;

    private ConvolutionKernel(int radiusX, int radiusY, float[] convolveKernel) {
        this.radiusX = radiusX;
        this.radiusY = radiusY;
        this.convolveKernel = convolveKernel;
    }

    public static ConvolutionKernel createGaussianKernel(float sd) {
        int r = (int) Math.ceil(sd * Math.E);
        int len = r * 2 + 1;
        float[] kern = new float[len * len];
        for (int x = -r; x <= r; x++) {
            for (int y = -r; y <= r; y++) {
                float f = (float) Math.exp(-((x * x + y * y) / (2 * sd * sd)));
                kern[index2D(x + r, y + r, len)] = f;
            }
        }
        return new ConvolutionKernel(r, r, kern);
    }

    public static ConvolutionKernel createGaussianKernel(float sdx, float sdy) {
        int rx = (int) Math.ceil(sdx * Math.E);
        int ry = (int) Math.ceil(sdy * Math.E);
        int lenx = rx * 2 + 1;
        int leny = ry * 2 + 1;
        float[] kern = new float[lenx * leny];
        for (int x = -rx; x <= rx; x++) {
            for (int y = -ry; y <= ry; y++) {
                float f = (float) Math.exp(-(((x * x) / (2 * sdx * sdx))
                        + ((y * y) / (2 * sdy * sdy))));
                kern[index2D(x + rx, y + ry, leny)] = f;
            }
        }
        return new ConvolutionKernel(rx, ry, kern);
    }

    private static int index2D(int x, int y, int Y) {
        return y + x * Y;
    }
}
